﻿using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using System.Text.Json.Serialization;

namespace TemplateDemo.Common
{
    //[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class HiddenApiAttribute : System.Attribute
    {
    }
    public class HiddenAttribute : Attribute
    {
    }
    public static class DictionaryExtension
    {
        public static bool ContainsKeyIgnoreCase<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
        {
            bool? keyExists;

            var keyString = key as string;
            if (keyString != null)
            {
                // Key is a string.
                // Using string.Equals to perform case insensitive comparison of the dictionary key.
                keyExists =
                    dictionary.Keys.OfType<string>()
                    .Any(k => string.Equals(k, keyString, StringComparison.InvariantCultureIgnoreCase));
            }
            else
            {
                // Key is any other type, use default comparison.
                keyExists = dictionary.ContainsKey(key);
            }

            return keyExists ?? false;
        }
    }
    public class SwaggerExcludeAttribute : Attribute
    {
    }
    public class SwaggerExcludeFilter : ISchemaFilter
    {

        #region ISchemaFilter Members

        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (schema?.Properties == null || schema.Properties.Count <= 0)
            {
                return;
            }
            var at=  context.Type.GetCustomAttribute<HiddenAttribute>();
            if (at!=null)
            {
                schema.Properties = null;
                return;
            }
                    var excludedProperties = context.Type.GetProperties();
            foreach (var property in excludedProperties)
            {
                var attributes = property.GetCustomAttributes(true);
                var excludeAttributes = attributes.OfType<SwaggerExcludeAttribute>();
                if (excludeAttributes.Any()
                    && schema.Properties.ContainsKeyIgnoreCase(property.Name))
                {
                    RemoveIgnoreCase(schema.Properties, property.Name);
                }
            };
        }
        #endregion
        public bool RemoveIgnoreCase<TValue>(IDictionary<string, TValue> dictionary, string key)
        {
            foreach (var item in dictionary.Keys)
            {
                if (string.Equals(item, key, StringComparison.InvariantCultureIgnoreCase))
                {
                    dictionary.Remove(item);
                    return true;
                }
            }
            return false;
        }
    }

    //public class SwaggerOperationFilter : IOperationFilter
    //{
    //    /// <summary>
    //    /// 应用筛选
    //    /// </summary>
    //    /// <param name="operation"></param>
    //    /// <param name="context"></param>
    //    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    //    {
    //        //获取参数类型
    //        var type = context.ApiDescription.ActionDescriptor.Parameters.FirstOrDefault()?.ParameterType;

    //        var proty = type?.GetProperties() ?? new PropertyInfo[] { };

    //        foreach (var item in proty)
    //        {

    //            //查找忽略Attribute
    //            var attr = item.GetCustomAttribute<HiddenAttribute>();
    //            if (attr == null)
    //                continue;

    //            //查找忽略参数
    //            var param = operation.Parameters.FirstOrDefault(p => p.Name == item.Name);
    //            if (param != null)
    //                operation.Parameters.Remove(param);

    //        }
    //    }
    //}
    public class HiddenApiFilter : IDocumentFilter
    {
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {

            foreach (ApiDescription apiDescription in context.ApiDescriptions)
            {
                if (apiDescription.TryGetMethodInfo(out MethodInfo method))
                {
                    if (method.ReflectedType.CustomAttributes.Any(t => t.AttributeType == typeof(HiddenApiAttribute))
                            || method.CustomAttributes.Any(t => t.AttributeType == typeof(HiddenApiAttribute)))
                    {
                        string key = "/" + apiDescription.RelativePath;
                        if (key.Contains("?"))
                        {
                            int idx = key.IndexOf("?", System.StringComparison.Ordinal);
                            key = key.Substring(0, idx);
                        }
                        swaggerDoc.Paths.Remove(key);
                    }
                }
            }
        }
    }
}
